home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
ipalias.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-22
|
10KB
|
431 lines
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netdb.h>
#include "netconf.h"
#include "../userconf/userconf.h"
#include "internal.h"
#include "../misc/misc.h"
#include "../paths.h"
#include "netconf.m"
static NETCONF_HELP_FILE help_aliases ("ip_aliases");
static CONFIG_FILE f_aliases (PROC_NET_ALIASES
,help_aliases
,CONFIGF_OPTIONNAL|CONFIGF_PROBED);
static CONFIG_FILE f_alias_types (PROC_NET_ALIAS_TYPES
,help_aliases
,CONFIGF_OPTIONNAL|CONFIGF_PROBED);
/* #Specification: netconf / aliases / strategy
linuxconf will automaticly manage/assign/remove all ip_alias based
on the definitions it received. It will select by itself the
alias number (ethx:NUMBER) by monitoring the currently allocated
ones.
*/
PUBLIC IP_ALIAS::IP_ALIAS(int _num, const char *_ip)
{
num = _num;
ip.setfrom (_ip);
}
PUBLIC IP_ALIAS::IP_ALIAS(const char *_ip)
{
num = -1; // Not yet setup in the kernel
ip.setfrom (_ip);
}
PUBLIC int IP_ALIAS::unset (const char *devname)
{
char cmd[100];
sprintf (cmd,"%s:%d- 0.0.0.0",devname,num);
return netconf_system_if ("ifconfig",cmd);
}
PUBLIC int IP_ALIAS::set (int _num, const char *devname)
{
char cmd[100];
sprintf (cmd,"%s:%d %s",devname,_num,ip.get());
int ret = netconf_system_if ("ifconfig",cmd);
if (ret == 0){
sprintf (cmd,"add %s %s:%d",ip.get(),devname,_num);
ret = netconf_system_if ("route",cmd);
}
return ret;
}
PUBLIC IP_ALIAS *IP_ALIASES::getitem(int no)
{
return (IP_ALIAS*)ARRAY::getitem(no);
}
/*
Locate one alias from its IP number
*/
PUBLIC IP_ALIAS *IP_ALIASES::getitem(const char *ip)
{
IP_ALIAS *ret = NULL;
int n = getnb();
for (int i=0; i<n; i++){
IP_ALIAS *a = getitem(i);
if (a->ip.cmp(ip)==0){
ret = a;
break;
}
}
return ret;
}
/*
Read the aliases currently configured for a device (eth0 for example)
*/
PUBLIC void IP_ALIASES::readproc (const char *devname)
{
FILE *fin = f_aliases.fopen ("r");
if (fin != NULL){
char buf[300];
int len = strlen(devname);
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
if (strncmp(buf,devname,len)==0
&& buf[len] == ':'){
int id;
int family;
char ip[100];
sscanf (buf+len+1,"%d %d %s",&id,&family,ip);
/* #Specification: netconf / aliases / 0.0.0.0
The file /proc/net/aliases contains entries
with an IP number of 0.0.0.0. Theses entries
are "downed" interface. I suspect they should be
left out of the table. Anyway, they are ignored
by linuxconf.
*/
if (strcmp(ip,"0.0.0.0")!=0){
add (new IP_ALIAS(id,ip));
}
}
}
fclose (fin);
}
}
/*
Return the number of the last allocated alias numer (ethx:N)
*/
PUBLIC int IP_ALIASES::getmaxnum()
{
int ret = 0;
int n = getnb();
for (int i=0; i<n; i++){
IP_ALIAS *a = getitem(i);
if (a->num > ret) ret = a->num;
}
return ret;
}
/*
Translate a IP number into up to four numbers.
Return the number of numbers written into tbi.
*/
static int ipalias_evalip (const char *str, int tbi[4])
{
int nb = 0;
while (*str != '\0'){
tbi[nb++] = atoi(str);
str = str_skipdig (str);
if (*str == '.') str++;
}
return nb;
}
/*
Record the aliases definition.
The function setup has to be called after setting all the definition
*/
PUBLIC int IP_ALIASES::setnew (
const char *devip, // Ip number of the device
const char *ips, // A bunch of IP alias to allocate
char *err) // Collect error messages
{
/* #Specification: netconf / aliases / defining many
The user interface of linuxconf allows you to define several
IP aliases for a device. These aliases are generally used for
virtual host httpd server. Many installation will required a fair
amount of IP number, one for each domain they serve. To help setup
those aliases, linuxconf do support different syntax.
#
-You can define menu IP number on a single line.
-You can define a range of IP number like this x.y.z.a-b. This
will effectivly define one alias per number from a to b.
-You can define an alias just by specifying the suffix of the
ip number. For example, an ethernet device (eth0) may have the IP
192.168.1.1. By defining the alias 2 3 4 5, you are effectivly
defining:
eth0:1 192.168.1.2
eth0:2 192.168.1.3
eth0:3 192.168.1.4
eth0:4 192.168.1.5
-The abreviated syntax define in the previous paragraph also work
with ranges. The previous example could be written 2-5.
-You can use names (fqdn) to setup aliases.
#
*/
int ret = 0;
while (1){
ips = str_skip(ips);
if (*ips == '\0') break;
char word[200];
ips = str_copyword (word,ips);
if (isdigit (word[0])){
char *pt = strchr(word,'-');
int start=0,end=0;
if (pt != NULL){
*pt++ = '\0';
end = atoi(pt);
}
char *first = strrchr(word,'.');
if (first != NULL){
*first++ = '\0';
start = atoi(first);
}else{
start = atoi(word);
word[0] = '\0';
}
if (end < start) end = start;
int tbdev[4];
ipalias_evalip(devip,tbdev);
int tbspec[4];
int nbspec = ipalias_evalip(word,tbspec);
memcpy (tbdev+(3-nbspec),tbspec,nbspec*sizeof(int));
for (int i=start; i<=end; i++){
sprintf (word,"%d.%d.%d.%d",tbdev[0],tbdev[1],tbdev[2],i);
add (new IP_ALIAS (word));
}
}else{
struct hostent *ent = gethostbyname(word);
if (ent != NULL){
devices_ip2a (ent,word);
add (new IP_ALIAS(word));
}else{
strcat (err,MSG_U(E_UNKHOST,"Unknown host name "));
strcat (err,word);
strcat (err,"\n");
ret = -1;
}
}
}
return ret;
}
static int ipalias_available()
{
int ret = 0;
FILE *fin = f_alias_types.fopen("r");
if (fin == NULL){
xconf_error (MSG_U(E_NOALIAS,"No kernel support for devices aliasing"));
}else{
char buf[300];
if (fgets(buf,sizeof(buf)-1,fin)!=NULL){
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
int id = atoi(buf);
if (id == AF_INET){
ret = 1;
break;
}
}
}
fclose (fin);
if (!ret){
ret = netconf_system_if ("modprobe","ip_alias") == 0;
}
}
return ret;
}
/*
Install the proper aliases in the kernel.
Cleanup the one which are not needed anymore.
Return -1 if any errors.
*/
PUBLIC int IP_ALIASES::setup (const char *devname)
{
IP_ALIASES proc;
proc.readproc(devname);
int maxnum = proc.getmaxnum();
int n = getnb();
int len = maxnum+n+1;
char lookup[len];
memset (lookup,0,sizeof(char)*len);
IP_ALIASES toadd; // Will contain the items that must be added
toadd.neverdelete();
int i;
for (i=0; i<n; i++){
IP_ALIAS *a = getitem(i);
IP_ALIAS *ap = proc.getitem(a->ip.get());
if (ap != NULL){
// Alias is already installed
lookup[ap->num] = 1;
}else{
toadd.add(a);
}
}
int ret = 0;
n = proc.getnb();
for (i=0; i<n; i++){
IP_ALIAS *a = proc.getitem(i);
IP_ALIAS *ap = getitem(a->ip.get());
if (ap == NULL){
// Alias is already installed and must be removed
ret |= a->unset (devname);
}
}
n = toadd.getnb();
if (n > 0){
if (ipalias_available()){
int allocnum = 0;
for (i=0; i<n; i++){
IP_ALIAS *a = toadd.getitem(i);
while (lookup[allocnum] != 0) allocnum++;
ret |= a->set (allocnum,devname);
allocnum++;
}
}else{
ret = -1;
}
}
return ret;
}
static char IPALIAS[]="ipalias";
int alias_setup(const char *devname)
{
int ret = -1;
IFCONFIG_INFO info;
if (ifconfig_getinfo(devname,info)!=-1){
IP_ALIASES alias;
SSTRINGS strs;
linuxconf_getall (IPALIAS,devname,strs,0);
ret = 0;
char err[10000];
err[0] = '\0';
for (int i=0; i<strs.getnb(); i++){
SSTRING *s = strs.getitem(i);
ret |= alias.setnew (info.ip_addr,s->get(),err);
}
if (ret == 0){
ret = alias.setup(devname);
}else if (err[0] != '\0'){
xconf_error (MSG_U(E_SETALIAS
,"Invalid alias setup for device %s\n%s")
,devname,err);
}
}
return ret;
}
/*
Install the aliases for all devices
*/
int alias_setup ()
{
int ret = -1;
SSTRINGS list;
if (devlist_read (list) != -1){
int n = list.getnb();
ret = 0;
for (int i=0; i<n; i++){
SSTRING *s = list.getitem(i);
ret |= alias_setup (s->get());
}
}
return ret;
}
static void alias_edit(const char *devname)
{
SSTRINGS lst;
linuxconf_getall (IPALIAS,devname,lst,1);
int i;
for (i=0; i<10; i++) lst.add(new SSTRING);
int nof = 0;
while (1){
DIALOG dia;
for (i=0; i<lst.getnb(); i++){
dia.newf_str (i==0 ? MSG_U(F_IPALIASES,"IP aliases") : ""
,*lst.getitem(i));
}
char buf[100];
sprintf (buf,MSG_U(T_IPALIASFORDEV,"IP aliases for device %s")
,devname);
MENU_STATUS code = dia.edit (buf
,MSG_U(I_IPALIASFORDEV
,"You can enter alternative IP numbers for a\n"
"network interface. You can enter several numbers\n"
"per lines. Many time savers syntax are supported\n"
"Here are some examples for:\n"
" 192.168.1.10 192.168.1.11 192.168.1.12\n"
" 192.168.1.10-12\n"
" 10-12")
,help_aliases
,nof);
if (code == MENU_CANCEL || code == MENU_ESCAPE){
break;
}else if (code == MENU_ACCEPT){
if (perm_rootaccess(MSG_U(P_UPDALIAS,"to update IP aliases"))){
for (i=0; i<lst.getnb(); i++){
SSTRING *s = lst.getitem(i);
if (s->is_empty()){
lst.remove_del (s);
i--;
}
}
linuxconf_replace (IPALIAS,devname,lst);
linuxconf_save();
break;
}
}
}
}
void alias_edit()
{
SSTRINGS lst;
if (devlist_read(lst)!=-1){
int sel = 0;
while (1){
DIALOG dia;
int n = lst.getnb();
lst.sort();
for (int i=0; i<n; i++){
dia.new_menuitem ("",lst.getitem(i)->get());
}
MENU_STATUS code = dia.editmenu (
MSG_U(T_IPALIASES,"Edit IP aliases configurations")
,MSG_U(I_SYSTEMS,"Each network device may have several\n"
"IP number. Alternate ones are called alias and are\n"
"entered here.\n")
,help_aliases
,sel,0);
if (code == MENU_OK){
if (n > 0){
SSTRING *s = lst.getitem(sel);
alias_edit (s->get());
}
}else if (code == MENU_ESCAPE || code == MENU_QUIT){
break;
}
}
}
}